package com.zhangtao.demo.config.redis.nettyclient;

import java.util.Scanner;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import com.zhangtao.demo.config.redis.nettyclient.handler.RedisClientHandler;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.redis.RedisArrayAggregator;
import io.netty.handler.codec.redis.RedisBulkStringAggregator;
import io.netty.handler.codec.redis.RedisDecoder;
import io.netty.handler.codec.redis.RedisEncoder;
import io.netty.util.AttributeKey;

@Component
public class NettyClient {

	public static final String REDIS_AUTH = "REDIS_AUTH";
	public static final String REDIS_DB = "REDIS_DB";
	public static AttributeKey<String> redisAuth = AttributeKey.newInstance(REDIS_AUTH);
	public static AttributeKey<Integer> redisdb = AttributeKey.newInstance(REDIS_DB);
	private Bootstrap b;
	private Channel channel;

	public NettyClient() {
		init();
	}

	@PostConstruct
	private void init() {
		NioEventLoopGroup worker = new NioEventLoopGroup();
		b = new Bootstrap();
		b.group(worker).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
				.option(ChannelOption.SO_KEEPALIVE, true).handler(new ChannelInitializer<NioSocketChannel>() {

					@Override
					protected void initChannel(NioSocketChannel ch) {
						ch.pipeline().addLast(new RedisDecoder()).addLast(new RedisBulkStringAggregator())
								.addLast(new RedisArrayAggregator()).addLast(new RedisEncoder())
								.addLast(new RedisClientHandler());
					}
				});
	}

	public void connect(String host, int port, String auth, int db) {
		if (this.channel != null && this.channel.isActive()) {
			this.channel.close();
		}
		if (StringUtils.isNotBlank(auth)) {
			b.attr(redisAuth, auth);
		}
		b.attr(redisdb, db).connect(host, port).addListener(f -> {
			if (f.isSuccess()) {
				channel = ((ChannelFuture) f).channel();
				Scanner scanner = new Scanner(System.in);
				new Thread(() -> {
					while (!Thread.interrupted()) {
						channel.writeAndFlush(scanner.nextLine());
						// channel.writeAndFlush(RedisUtils.getCommond(scanner.nextLine()));
					}
				}).start();
			}
		});
	}

	public static void main(String[] args) {
		NettyClient nclient = new NettyClient();
		nclient.connect("localhost", 6379, null, 0);
//		nclient.connect("10.135.80.34", 60965, "Pass1234", 0);
	}
}
